﻿/********************************************************************************
** auth： Mine
** date： 2016/12/19 23:35:40
** desc： 加密/解密工具类
** Ver.:  V1.0.0
*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace X_Code
{
   static class EncryptUtils
    {
       /// <summary>
       /// 使用md5 对 一段非空字符串按照 特有方法 二次 加密
       /// </summary>
       /// <returns></returns>
        public static String  getMineMD5(String str){
            if (string.IsNullOrEmpty(str))
            {
                throw new Exception("非法长度的源字符串。。。");
            }

            byte[] fromData = System.Text.Encoding.UTF8.GetBytes(str); //源字符串转换为数组
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] md5Data = md5.ComputeHash(fromData);
            //按照特定方式获取第二次MD5校验的数组

            int x= fromData.Length;
            int y= md5Data.Length;

            int oneSize = (x <= y) ? (x / 2) : (y / 2 -1);
            for (int i = 0; i < oneSize; i++)
            {
                md5Data[i] = fromData[i]; 
                md5Data[(y-1) - i] = fromData[(x-1) - i];
            }

            md5Data = md5.ComputeHash(md5Data);

            return BitConverter.ToString(md5Data).Replace("-","");
        }
        //Cryptography 密码术

        //Decrypt 解密
        public static String Encrypt(String str,String key)
        {
            return null;
        }
        public static String Decrypt(String str, String key)
        {
            return null;
        }
       /// <summary>
       /// AES cbc模式加密
       /// </summary>
       /// <param name="toEncrypt"></param>
       /// <param name="key"></param>
       /// <param name="iv"></param>
       /// <returns></returns>
        public static string AES_CBC_Encrypt(string encryptStr, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(encryptStr);
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros;
            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        /// AES cbc模式加密,byte[]版
        /// </summary>
        /// <param name="decryptDate"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public static byte[] AES_CBC_Encrypt_Byte(byte[] encryptData, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.PKCS7;
            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(encryptData, 0, encryptData.Length);
            return resultArray;
        }
        /// <summary>
        /// AES cbc模式解密,字符串版
        /// </summary>
        /// <param name="toEncrypt"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public static string AES_CBC_Decrypt(string decryptStr, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = Convert.FromBase64String(decryptStr);
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros;
            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return UTF8Encoding.UTF8.GetString(resultArray);
        }
       /// <summary>
        /// AES cbc模式解密,byte[]版
       /// </summary>
       /// <param name="decryptDate"></param>
       /// <param name="key"></param>
       /// <param name="iv"></param>
       /// <returns></returns>
        public static byte[] AES_CBC_Decrypt_Byte(byte[]  decryptDate, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros; //如果改用和加密一样的填充方式(addingMode.PKCS7)会有小概率情况抛出“填充无效，无法移除异常”
            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(decryptDate, 0, decryptDate.Length);
            return resultArray;
        }

       //循环输出数组值
        public static void ShowBytes(byte[] bytes)
        {
            Console.Write("bytes长度["+bytes.Length+"]:");
            foreach (byte one in bytes)
            {
                Console.Write("["+one+"],");
            }
            Console.WriteLine();
        }
        public static byte[] CreatAndInitBytes(int count)
        {
            byte[] data = new byte[count];
            for (int i = 0; i < count;i++ )
            {
                data[i] = (byte)i;
            }
            return data;
        }
    }
}
